package cn.buk.tms.eotms.service;

import cn.buk.common.JsonResult;
import cn.buk.common.util.DateUtil;
import cn.buk.tms.common.constant.TmsOrderConstant;
import cn.buk.tms.eotms.dao.ChangeOrderDao;
import cn.buk.tms.eotms.dao.FlightOrderDao;
import cn.buk.tms.eotms.dao.OrderNoGenerator;
import cn.buk.tms.eotms.dto.FlightChangeOrderDetailDto;
import cn.buk.tms.eotms.dto.FlightRefundTicket;
import cn.buk.tms.eotms.dto.RoleInfo;
import cn.buk.tms.eotms.entity.Customer;
import cn.buk.tms.eotms.entity.FlightChangeOrder;
import cn.buk.tms.eotms.entity.FlightChangeOrderDetail;
import cn.buk.tms.eotms.entity.FlightOrder;
import cn.buk.tms.eotms.request.ChangeOrderRequestDto;
import cn.buk.tms.eotms.response.ChangeOrderResponseDto;
import cn.buk.tms.eotms.sc.SearchFlightOrderCriteria;
import cn.buk.tms.eotms.util.FlightTicketUtil;
import cn.buk.tms.exception.BaseException;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

@Service
public class ChangeOrderServiceImpl extends BaseAbstractService implements ChangeOrderService {

  private static final Logger logger = Logger.getLogger(ChangeOrderServiceImpl.class);

  @Autowired
  private ChangeOrderDao changeOrderDao;

  @Autowired
  private OrderNoGenerator orderNoGenerator;

  @Autowired
  private FlightOrderDao flightOrderDao;


  @Override
  public List<ChangeOrderResponseDto> searchChangeOrders(int userId, SearchFlightOrderCriteria sc) {
    final int ownerId = getOwnerIdByUserId(userId);
    final int customerId = getCustomerIdByUserId(userId);
    final int enterpriseId = getEnterpriseIdByUserId(userId);
    final String username = getUsernameByUserId(userId);

    Set<String> roles = getRolesByUserId(enterpriseId, userId);
    //管理员可以查看所有的员工信息
    //其它可以查看本部门所有的员工信息
    if (roles.contains(RoleInfo.ROLE_ADMIN)) {
      //管理员可以查看所有部门的订单
    } else if (roles.contains(RoleInfo.ROLE_MANAGER) || roles.contains(RoleInfo.ROLE_APPROVER)){
      //只能查看本部门的
      int deptId = getCustomerDeptIdByUserId(userId);
      sc.setDepartmentId(deptId);
    } else {
      //只能查看自己的订单
      sc.setOp1(username);
    }

    List<FlightChangeOrder> list = changeOrderDao.searchFlightChangeOrder(ownerId, customerId, sc);

    List<ChangeOrderResponseDto> dtos = new ArrayList<>();

    for(FlightChangeOrder info : list) {
      dtos.add(ChangeOrderResponseDto.createdBy(info));
    }

    return dtos;
  }

  @Override
  public ChangeOrderResponseDto getFlightChangeOrderDetail(final int userId, final int id) throws BaseException {
    final int ownerId = getOwnerIdByUserId(userId);
    final int customerId = getCustomerIdByUserId(userId);

    FlightChangeOrder o = changeOrderDao.getFlightChangeOrderDetail(id);

    if (o == null || o.getEnterpriseId() != ownerId || o.getCustomer().getId() != customerId) {
      throw new BaseException(30001, "订单不存在或无权访问");
    }

    for (FlightChangeOrderDetail detail : o.getFlights()) {
      detail.setOrder(null);
    }

    ChangeOrderResponseDto dto = ChangeOrderResponseDto.createdBy(o);

    dto.setErrcode(0);

    return dto;
  }

  @Override
  public JsonResult createFlightChangeOrder(final int userId, ChangeOrderRequestDto dto) throws BaseException {
    final int ownerId = getOwnerIdByUserId(userId);
    final int customerId = getCustomerIdByUserId(userId);

    int selectCount = 0;
    for (var t : dto.getTickets()) {
      if (!t.isSelected()) {
        continue;
      }

      selectCount++;

      if (!FlightTicketUtil.verifyTicketNo(t.getTicketNo())) {
        throw new BaseException(20025, "票号格式不符合要求");
      }

      if (StringUtils.trimToEmpty(t.getName()).length() == 0) {
        throw new BaseException(20037, "改签乘机人的姓名");
      }

      if (StringUtils.trimToEmpty(t.getIdNo()).length() == 0) {
        throw new BaseException(20038, "改签乘机人的证件号");
      }

      final String ticketNo0 = t.getTicketNo();
      final String balCode = ticketNo0.substring(0, 3);
      final String tickNo =
              ticketNo0.length() == 14 ? ticketNo0.substring(4) : ticketNo0.substring(3);

      // 检查该票号是否已经改签订单
      var sc = new SearchFlightOrderCriteria();
      sc.setBalCode(balCode);
      sc.setTicketNo(tickNo);
      var orders = changeOrderDao.searchFlightChangeOrder(ownerId, customerId, sc);
      for (var order : orders) {
        if (order.getChangeCount() >= dto.getChangeCount()) {
          throw new BaseException(20037, ticketNo0 + "-该票号已经创建了改签单(" + order.getChangeCount() + ")");
        }
      }

      //查找机票订单是否包含此票号
      var sc1 = new SearchFlightOrderCriteria();
      sc1.setTicketNo(tickNo);
      var flightOrders = flightOrderDao.searchOrder(ownerId, customerId, sc1);
      if (flightOrders.isEmpty()) {
        throw new BaseException(20030, balCode + tickNo + "-未找到和票号对应的机票订单");
      }

      //校验新航班的起飞日期、舱位
      int oldFlightCount = 0, newFlightCount = 0;
      for (var detailDto : dto.getFlights()) {
        if (detailDto.getFltType() == 0) {
          oldFlightCount++;
        } else if (detailDto.getFltType() == 1) {
          newFlightCount++;
        }


        //校验舱位
        if (detailDto.getSubclass() == null
                || detailDto.getSubclass().trim().length() == 0
                || detailDto.getSubclass().trim().length() > 2
        ) {
          throw new BaseException(20034, "改签航班的舱位");
        }

        //校验出发机场和到达机场
        if (StringUtils.trimToEmpty(detailDto.getDport()).length() != 3 ||
                StringUtils.trimToEmpty(detailDto.getAport()).length() != 3) {
          throw new BaseException(20035, "改签航班的出发或达到机场格式");
        }

        //校验出发机场和到达机场
        if (StringUtils.trimToEmpty(detailDto.getFlightNo()).length() < 4) {
          throw new BaseException(20036, "改签航班的航班号格式");
        }

        if (detailDto.getFltType() == 0) {
          //原航班
          continue;
        }

        try {
          if (!DateUtil.isValidateData(detailDto.getDdate())) {
            throw new BaseException(20004, "出发日期不能为空或格式不正确");
          }
          Date newDdate = DateUtil.convertToDate(detailDto.getDdate(), "yyyy-MM-dd");
          if (DateUtil.getCurDate().getTime() > newDdate.getTime()) {
            return JsonResult
                    .createJsonResult(-3, detailDto.getDdate() + "-起飞日期不能早于今天");
          }
        } catch (ParseException e) {
          logger.error(detailDto.getDdate() + ": " + e.getMessage());
        }


      }

      if (oldFlightCount == 0 || newFlightCount == 0) {
        throw new BaseException(20033, "改签航班信息有错误：原航班信息数" + oldFlightCount + ", 新航班信息数" + newFlightCount);
      }
    }

    if (selectCount < 1) {
      throw new BaseException(20032, "请选择需要改签的票号");
    }

    //TODO  需要校验改签后的航班的数据是否准确：三字代码，航班号，日期格式，时间格式

    int created = 0;
    int retCode = 0;
    for (FlightRefundTicket t : dto.getTickets()) {
      if (!t.isSelected()) {
        continue;
      }

      final String ticketNo0 = t.getTicketNo();
      final String balCode = ticketNo0.substring(0, 3);
      final String tickNo =
              ticketNo0.length() == 14 ? ticketNo0.substring(4) : ticketNo0.substring(3);

      retCode = doCreateChangeOrder(ownerId, customerId, getUsernameByUserId(userId), balCode, tickNo, t.getName(),
              t.getIdNo(), dto);
      if (retCode > 0) {
        created++;
      }
    }

    JsonResult jsonResult = JsonResult.createJsonResult(created);
    if (retCode > 0) {
      jsonResult.setReturnCode(retCode);
    } else if (retCode == -100) {
      jsonResult.setErrmsg("保存时出现错误，请检查是否已有改签单。");
    }

    return jsonResult;
  }

  private int doCreateChangeOrder(final int enterpriseId, final int customerId, String username, String balCode, String tickNo,
                                  String name, String idNo, ChangeOrderRequestDto dto) {
    var info = new FlightChangeOrder();

    //企业客户
    info.setCustomerType(1);
    Customer customer = new Customer();
    customer.setId(customerId);
    info.setCustomer(customer);

    info.setEnterpriseId(enterpriseId);
    info.setBalanceCode(balCode);
    info.setTicketNo(tickNo);
    info.setChangeCount(dto.getChangeCount());

    info.setPsgName(name);
    info.setIdNo(idNo);

    info.setParvalue(dto.getParvalue());
    info.setTax(dto.getTax());
    info.setAirChangeCharge(dto.getAirChangeFee());
    info.setServiceCharge(dto.getServiceCharge());

    info.setRemark(dto.getRemark());
    info.setOperator(username);

    info.setChangeType(dto.getReasonCode());

    info.setOrderId(dto.getOrderId());
    info.setOrderNo(dto.getOrderNo());
    info.setParentChangeOrderNo(dto.getParentChangeOrderNo());

    info.setIntlTicket(dto.getIntlTicket());

    info.setChangeOrderNo(
            orderNoGenerator.generateOrderNo(enterpriseId, TmsOrderConstant.ORDER_NO_FLIGHT_CHANGE_SELF_SERVICE));

    FlightOrder flightOrder = flightOrderDao.getOrderById(dto.getOrderId());
    if (flightOrder != null) {
      info.setCustomerType(flightOrder.getCustomerType());
      info.setCustomer(flightOrder.getCustomer());

      info.setCostCenter(flightOrder.getCostCenter());
      info.setProjectName(flightOrder.getProjectName());

      //TODO 需要补齐这2项数据
//      info.setSupplier(flightOrder.getSupplier());
//      info.setPaymentMethod(flightOrder.getPaymentMethod());

      info.setPayType(flightOrder.getPayType());
      info.setPayRemark(flightOrder.getPayRemark());
    }

    for (FlightChangeOrderDetailDto detailDto : dto.getFlights()) {
      FlightChangeOrderDetail detail = new FlightChangeOrderDetail();
      detail.setOrder(info);
      detail.setEnterpriseId(enterpriseId);

      detail.getFlight().setDepartureAirport(detailDto.getDport());
      detail.getFlight().setDepartureAirportName(detailDto.getDportName());
      detail.getFlight().setDepartureTerminal(detailDto.getDterm());

      detail.getFlight().setArrivalAirport(detailDto.getAport());
      detail.getFlight().setArrivalAirportName(detailDto.getAportName());
      detail.getFlight().setArrivalTerminal(detailDto.getAterm());

      detail.getFlight().setDepartureDate(detailDto.getDdate());
      detail.getFlight().setDepartureTime(detailDto.getDtime());
      detail.getFlight().setArrivalTime(detailDto.getAtime());

      detail.getFlight().setSubclass(detailDto.getSubclass());
      detail.getFlight().setFlightNo(detailDto.getFlightNo());

      detail.setFlightType(detailDto.getFltType());

      info.getFlights().add(detail);
    }

    int retCode = changeOrderDao.createFlightChangeOrder(info);
    if (retCode > 0) {
//      doSendAlert(enterpriseId, "有新的改签单了(" + info.getChangeOrderNo() + ")", null,
//              EntDepartment.DEPT_TICKETING);
    }

    return retCode;
  }

}
